# -*- conding:UTF-8 -*-

'''
@ Project: P8 flask_progect
@ File: oauth_user.py
@ Author: 罗婷
@ Date：2022/6/21 17:09
oauth_user_bp
'''
import base64
import hmac
import json
import time
import urllib
from urllib.parse import parse_qs

import requests
from flask import Blueprint, current_app
from flask_restful import Api, Resource, reqparse
from werkzeug.security import check_password_hash

from common.jwt.token_generate import generate_token
from common.models import db
from common.models.users import OAuthUserModel, Users
from common.utils.output_json import my_output_json

oauth_user_bp = Blueprint('oauth_user_bp', __name__, url_prefix='/oauth')
api = Api(oauth_user_bp)


# 自定义返回给前端的数据 使用重写的output_json 方法
@api.representation('application/json')
def output_json(data, code, headers=None):
    resp = my_output_json(data, code)
    return resp



# 三方登录

class DingDing_login(Resource):

    # 获取扫码登录的用户信息  需要传入扫码后的code
    # 构建数据三个参数
    #  accessKey  :appid(应用的id)  appSecret (秘钥)
    #  timestamp，(当前的时间戳，是单位毫秒)
    #  signature:(appSecret计算出来的签名值)
    def get_dingding_user(self, code):

        appid = current_app.config.get('DINGDING_APPID')
        appSecret = current_app.config.get('DINGDING_APPSECRET')
        timestamp = str(int(time.time())*1000)
        #   hmac.new()哈希加密后端对象    .digest()获取hash对象的值   encode('utf-8') 默认utf-8编码
        signature = base64.b64encode(hmac.new(appSecret.encode(), timestamp.encode(), digestmod='sha256').digest())
        # 官方文档里三方登录的地址
        base_url = "https://oapi.dingtalk.com/sns/getuserinfo_bycode?signature="

        #TODO 拼接url urllib  导包俩  地址容易出错  timestamp单词拼错
        url = base_url + urllib.parse.quote(signature.decode('utf-8')) + '&timestamp=' + timestamp + '&accessKey=' + appid

        # 获取的code
        data = json.dumps({'tmp_auth_code': code})
        # data = code
        try:
            resp = requests.post(url, data, headers={'Content-Type': 'application/json'})
            print('resp用户扫码的数据是---', resp.json())
        except Exception as e:
            print(f'用户扫码获取数据失败{e}')
            return {'code': 500, "message": 'post 获取钉钉用户信息失败'}

        user_info = resp.json()
        if user_info['errcode'] != 0:
            return {'code': 500, "message": '根据code获取钉钉用户信息失败'}
        # 获取成功 用户信息转字典
        user_info_dict = user_info['user_info']
        return user_info_dict

    def get(self):
        # 扫码时路由附带的code
        # 1 获取code
        # 2 根据code获取用户信息(在上边定义方法)
        # 3 发起请求
        parser = reqparse.RequestParser()
        parser.add_argument('code')
        args = parser.parse_args()
        code = args['code']
        # 使用封装的方法 获取当前登录的用户信息
        user_info = self.get_dingding_user(code)
        openid = user_info['openid']

        oather_user = OAuthUserModel.query.filter_by(oauth_id=openid, oauth_type='dingding').first()

        if oather_user:  # 成功查询 说明绑定过
            print('oather_user==========', oather_user)
            user = Users.query.filter_by(uid=oather_user.user).first()
            # TODO 生成token
            payload = {
                'user_id': user.uid,
                'user_name': user.account,
            }
            token = generate_token(payload)
            if token:
                return {'code': 200, "account": user.account, 'uid': user.uid,  'token': token}
        else:  # 成功失败 说明未绑定
            return {'massage': '未绑定, 请前往绑定', 'uid': openid}

class DingdingBindUser(Resource):
    # 绑定用户  微博钉钉
    """
    1 获取用户信息 3个 account password unid(openid)
    2 判断用户是否存在  查询数据库
        1 存在  校验密码  通过  绑定用户 三方登录表添加数据  生成token  返回指定数据
                        不通过  返回响应:密码错误
        2 不存在 返回响应:请注册用户

    :return:
    """
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument('account')
        parser.add_argument('password')
        parser.add_argument('unid')
        args = parser.parse_args()
        account = args['account']
        password = args['password']
        openid = args['unid']
        try:
            user = Users.query.filter_by(account=account).first()
        except Exception as e:
            return {'message': '查询用户失败', 'code': 500}

        if not user:
            return {'message': '用户未注册', 'code': 400}

        pwd_bool = check_password_hash(user.password, password)
        if not pwd_bool:
            return {'message': '密码错误', 'code': 400}

        # 密码正确 绑定用户
        user_oauth = OAuthUserModel(oauth_id=openid, user=user.uid, oauth_type='dingding')
        db.session.add(user_oauth)
        db.session.commit()
        # 生成token
        payload = {
            'user_id': user.uid,
            'user_name': user.account,
        }
        token = generate_token(payload)
        if token:
            return {'message': '绑定成功', 'code': 200, "account": user.account, 'uid': user.uid, 'token': token}

# 微博三方登录
class Weibo_login(Resource):
    def get_weibo_user(self, code):
        # 构造参数获取weibo的用户信息
        base_url = 'https://api.weibo.com/oauth2/access_token'
        data_ = {
            "client_id": "2775107052",
            "client_secret": "718b38b04fc387700cc1595b30875b19",
            "grant_type": "authorization_code",
            "redirect_uri": "http://127.0.0.1:8080/weibo",
            "code": code,
        }
        try:
            resp = requests.post(url=base_url, data=data_).json()
            print("resp=========>", resp)
        except Exception as e:
            print(f'获取微博用户数据失败{e}')
            return {'code': 500, "message": 'post 获取微博用户信息失败'}
        if not resp['access_token']:
            return {'code': 400, "message": '根据code获取微博用户信息失败'}
        user_info = resp
        return user_info



    def get(self):
        """根据code 获取微博用户信息"""
        # 返回数据格式
        # {
        #     "access_token": "ACCESS_TOKEN",  client_secret  秘钥
        #     "expires_in": 1234,             过期时间
        #     "remind_in": "798114",
        #     "uid": "12341234"                用户扫码的id 类似于订单的openid
        # }

        parser = reqparse.RequestParser()
        parser.add_argument('code')
        args = parser.parse_args()
        # 1.获取code值
        code = args.get('code')
        print('code======', code)
        user_info = self.get_weibo_user(code)
        print('user_info---xxxxxxxxx', user_info)
        access_token = user_info['access_token']
        weibo_user = OAuthUserModel.query.filter_by(oauth_id=access_token, oauth_type='weibo').first()
        if not weibo_user:  # 未绑定  响应去绑定
            return {'massage': '未绑定, 请前往绑定', 'uid': access_token, 'code': 400}

        else:   # 绑定 查询用户数据  生成token 返回响应
            user = Users.query.filter_by(uid=weibo_user.user).first()
            payload = {
                'user_id': user.uid,
                'user_name': user.account,
            }
            token = generate_token(payload)
            if token:
                return {'code': 200, "account": user.account, 'uid': user.uid, 'token': token}

# 绑定微博
class WeiboBindUser(Resource):
    def post(self):
        # 接收数据 判断用户是否存在  存在 校验密码  通过校验加入三方表  生成token   不存在 响应注册
        parser = reqparse.RequestParser()
        argss = ['account', 'password', 'unid']
        for i in argss:
            parser.add_argument(i)
        args = parser.parse_args()
        account = args['account']
        password = args['password']
        unid = args['unid']   # access_token

        user = Users.query.filter_by(account=account).first()
        if not user:
            return {'message': '请先注册', 'code': 400}

        pwd_bool = check_password_hash(user.password, password)
        if not pwd_bool:
            return {'message': '密码错误', 'code': 400}
        # 加入三方表
        user_weibo = OAuthUserModel(oauth_id=unid, user=user.uid, oauth_type='weibo')
        db.session.add(user_weibo)
        db.session.commit()
        # 生成token
        payload = {
            'user_id': user.uid,
            'user_name': account,
        }
        token = generate_token(payload)
        return {'code': 200, 'account': account, 'token': token, 'uid': user.uid}



api.add_resource(DingDing_login, '/dingding')
api.add_resource(DingdingBindUser, '/dingding/bind')

api.add_resource(Weibo_login, '/weibo')
# api.add_resource(WeiboBindUser, '/weibo/bind')






